package nio;

import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * @author lzy
 * @version v1.0
 * Create DateTime: 2018/8/25 10:02
 * <p>
 * 一、使用NIO完成网络通信的三个核心
 * 1.通道(Channel)：负责连接
 * java.nio.channels.Channel接口
 * |--SelectableChannel
 * |--SocketChannel (TCP client)
 * |--ServerSocketChannel (TCP server)
 * |--DatagramChannel (UDP)
 * |--Pipe.SinkChannel
 * |--Pipe.SourceChannel
 * <p>
 * 注意：SelectableChannel下没有FileChannel，因为FileChannel无法切换到非阻塞模式，非阻塞模式主要是指网络IO
 * <p>
 * 2.缓冲区(Buffer):负责数据的存取
 * <p>
 * 3.选择器(Selector)：是SelectableChannel的多路复用器，用于监控SelectableChannel的IO状况
 */
public class BlockingNIOTest {
    // 客户端
    @Test
    public void testClient() {
        try (//1. 获取通道
             SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
             FileChannel inChannel = FileChannel.open(Paths.get("D:\\1.jpg"), StandardOpenOption.READ)) {
            //2.分配指定大小的缓冲区
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            //3.读取本地文件，并发送到服务器
            while (inChannel.read(buffer) != -1) {
                buffer.flip();
                socketChannel.write(buffer);
                buffer.clear();
            }

            //4.关闭通道: 使用了jdk1.7的autoCloseable接口
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    // 服务端
    @Test
    public void testServer() {
        // 1.获取通道
        try (ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
             FileChannel fileChannel = FileChannel.open(Paths.get("D:\\2.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE)) {
            // 2.绑定连接
            serverSocketChannel.bind(new InetSocketAddress(9898));
            // 3.获取客户端连接的通道
            SocketChannel socketChannel = serverSocketChannel.accept();
            // 4.接收客户端的数据，并保存到本地
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            while (socketChannel.read(buffer) != -1) {
                buffer.flip();
                fileChannel.write(buffer);
                buffer.clear();
            }

            // 关闭连接
            socketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
